<?php

declare(strict_types=1);
/**
 * 模型服务类
 * Author: Zane
 * Email: 873934580@qq.com
 * Date: 2023/6/19.
 */

namespace App\Service;

use App\Enum\DefaultFieldEnum;
use App\Exceptions\CommonExceptionConstants;
use App\Exceptions\ServiceException;
use App\Models\ChannelModel;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class ChannelModelService
{
    public function __construct()
    {
    }

    public function lists($search = []): array
    {
        $filterMap = ChannelModel::query();

        return $filterMap->orderBy('weight', 'desc')->paginate()->toArray();
    }

    public function store($data): void
    {
        DB::beginTransaction();

        try {
            $model = ChannelModel::query()->create($data);
            $this->createTable($model);
            DB::commit();
        } catch (\Exception $e) {
            // 如果数据表字段创建失败测需要直接删除对应的字段信息
            // ChannelModel::destroy($id);
            // ChannelModel::withTrashed()->where('id', $id)->forceDelete();
            DB::rollBack();

            throw new ServiceException(['message' => $e->getMessage()]);
        }
    }

    public function edit($data, $id): void
    {
        DB::beginTransaction();

        try {
            $model = ChannelModel::byId($id);
            $oldModel = clone $model;
            $model->update($data);
            $this->editTableName($model, $oldModel);
            DB::commit();
        } catch (\Exception $e) {
            // $oldModel->save();
            DB::rollBack();

            throw new ServiceException(['message' => $e->getMessage()]);
        }
    }

    /**
     * 彻底删除数据，同时会将数据表一起删除.
     *
     * @param $id
     */
    public function delTable($id): void
    {
        $dao = ChannelModel::query()->where('id', $id)->first();
        if ($dao) {
            $dao->delete();

            return;
        }
        $dao = ChannelModel::withTrashed()->where('id', $id)->first();
        if (!$dao) {
            throw new ServiceException(CommonExceptionConstants::NO_FIND_DATA);
        }
        $table = getTableName($dao->table_name);
        // 彻底删除
        $dao->forceDelete();
        Schema::dropIfExists($table);
    }

    /**
     * 确保数据表存在.
     *
     * @param mixed $id
     */
    public static function ensureTableExists($id): void
    {
        $dao = ChannelModel::byId($id);
        $table = getTableName($dao->table_name);
        if (!Schema::hasTable($table)) {
            (new static())->createTable($dao);
        }
    }

    /**
     * 修改数据表名称.
     *
     * @param $dao
     * @param $origin
     */
    private function editTableName($dao, $origin): void
    {
        if ($dao->table_name !== $origin->table_name) {
            $table = getTableName($dao->table_name);
            $tableName = getTableName($origin->table_name);
            if (Schema::hasTable($table)) {
                throw new ServiceException(CommonExceptionConstants::DATA_IS_EXISTS);
            }
            if (!Schema::hasTable($tableName)) {
                throw new ServiceException(CommonExceptionConstants::DATA_IS_EXISTS);
            }
            Schema::rename($tableName, $table);
        }
    }

    /**
     * 新增数据表.
     *
     * @param $model
     */
    private function createTable($model): void
    {
        $table = getTableName($model->table_name);
        if (Schema::hasTable($table)) {
            throw new ServiceException(CommonExceptionConstants::DATA_IS_EXISTS);
        }

        // 新增数据表并创建默认字段
        Schema::create($table, function (Blueprint $table) use ($model): void {
            $table->id();
            // $table->bigInteger(DefaultFieldEnum::CATEGORY_ID)->unsigned()->default(0);
            // $table->string(DefaultFieldEnum::TITLE, 300)->default('');
            $table->string(DefaultFieldEnum::LANG, 50)->default(app()->getLocale());
            $table->tinyInteger(DefaultFieldEnum::STATUS)->unsigned()->default(1);
            $table->bigInteger(DefaultFieldEnum::DELETED_AT)->nullable();
            $table->bigInteger(DefaultFieldEnum::CREATOR_ID)->unsigned()->default(0);
            $table->bigInteger(DefaultFieldEnum::UPDATER_ID)->unsigned()->default(0);
            $table->bigInteger(DefaultFieldEnum::CREATED_AT)->unsigned()->default(0);
            $table->bigInteger(DefaultFieldEnum::UPDATED_AT)->unsigned()->default(0);
            if (!$model->is_one_page) {
                $table->integer(DefaultFieldEnum::WEIGHT)->unsigned()->default(99);
            }
        });
    }
}
